﻿using System;
using System.ServiceModel.DomainServices.Client;
using GalaSoft.MvvmLight;
using ErickOrlando.Utilidades.Data;

namespace ErickOrlando.Utilidades.Mvvm
{
	/// <summary>
	/// Clase base para las clases complejas
	/// </summary>
	public abstract class ComplexClass : ComplexObject
	{
		#region Variables
		private string _errorMessage;
		private bool _isCancelEnabled;
		private bool _isDeleteEnabled;
		private bool _isEditEnabled;
		private bool _isEditing;
		private bool _isNew;
		private bool _isNewEnabled;
		private bool _isSaveEnabled;
		private OperationStatus _Status;
		#endregion

		#region Constructor
		protected internal ComplexClass()
		{
			IsNew = true;
			IsNewEnabled = true;
			DeleteCompletedEvent += OnDeleteCompleted;
			ListCompletedEvent += OnListCompleted;
			SaveCompletedEvent += OnSaveCompleted;
		}
		#endregion

		#region Propiedades

		public string ErrorMessage
		{
			get
			{
				if (Status != null)
					_errorMessage = Status.Message;
				else
					_errorMessage = string.Empty;
				return _errorMessage;
			}
			set
			{
				_errorMessage = value;
				RaisePropertyChanged("ErrorMessage");
			}
		}

		public bool IsCancelEnabled
		{
			get { return _isCancelEnabled; }
			set
			{

				_isCancelEnabled = value;
				RaisePropertyChanged("IsCancelEnabled");
			}
		}

		public bool IsDeleteEnabled
		{
			get { return _isDeleteEnabled; }
			set
			{

				_isDeleteEnabled = value;
				RaisePropertyChanged("IsDeleteEnabled");
			}
		}

		public bool IsEditEnabled
		{
			get { return _isEditEnabled; }
			set
			{

				_isEditEnabled = value;
				RaisePropertyChanged("IsEditEnabled");
			}
		}

		public bool IsEditing
		{
			get { return _isEditing; }
			set
			{
				_isEditing = value;
				RaisePropertyChanged("IsEditing");
			}
		}

		public bool IsNew
		{
			get { return _isNew; }
			set
			{
				_isNew = value;
				RaisePropertyChanged("IsNew");
			}
		}

		public bool IsNewEnabled
		{
			get { return _isNewEnabled; }
			set
			{

				_isNewEnabled = value;
				RaisePropertyChanged("IsNewEnabled");
			}
		}

		public bool IsSaveEnabled
		{
			get { return _isSaveEnabled; }
			set
			{

				_isSaveEnabled = value;
				RaisePropertyChanged("IsSaveEnabled");
			}
		}

		public OperationStatus Status
		{
			get { return _Status; }
			set
			{
				_Status = value;
				RaisePropertyChanged("Status");
				RaisePropertyChanged("ErrorMessage");
			}
		}

		private bool _waitingOperation;
		public bool WaitOperation
		{
			get { return _waitingOperation; }
			set
			{

				_waitingOperation = value;
				RaisePropertyChanged("WaitOperation");
			}
		}
		#endregion

		#region Metodos Virtuales

		public virtual void Cancel()
		{
			CancelEdit();
			IsEditing = false;
			Clean();
			EnableStates(false);
		}

		public virtual void Create()
		{
			IsNew = true;
			IsEditing = true;
			Clean();
			EnableStates(true);
		}

		public virtual void Delete()
		{
			if (IsNew)
				throw new InvalidOperationException("No se puede eliminar");
			WaitOperation = true;
		}

		public virtual void Edit()
		{
			IsNew = false;
			IsEditing = true;
			BeginEdit();
			EnableStates(true);
		}

		public virtual void List()
		{
			IsNew = true;
			IsEditing = false;
			Clean();
		}

		public virtual void Save()
		{
			IsEditing = false;
			WaitOperation = true;
			if (!IsNew)
				EndEdit();
			EnableStates(false);
		}

		public virtual void Clean()
		{

		}
		#endregion

		#region Metodos Privados


		private void EnableStates(bool valor)
		{
			IsNewEnabled = !valor;
			IsEditEnabled = !valor;
			IsSaveEnabled = valor;
			IsCancelEnabled = valor;
			IsDeleteEnabled = !valor;
		}
		#endregion

		#region Eventos

		/// <summary>
		/// Evento que se debe invocar cuando se complete la eliminación
		/// </summary>
		public virtual event Action DeleteCompletedEvent = delegate { };

		/// <summary>
		/// Evento que se debe invocar cuando se complete de cargar la lista
		/// </summary>
		public virtual event Action ListCompletedEvent = delegate { };

		/// <summary>
		/// Evento que se debe invocar cuando se complete la operacion de Guardado
		/// </summary>
		public virtual event Action SaveCompletedEvent = delegate { };


		/// <summary>
		/// Manejador de Eventos para DeleteCompletedEvent
		/// </summary>
		public virtual void OnDeleteCompleted()
		{
			WaitOperation = false;
			Clean();
			if (string.IsNullOrEmpty(ErrorMessage))
				ErrorMessage = "Registro eliminado con éxito!";
		}

		/// <summary>
		/// Manejador de Eventos para ListCompletedEvent
		/// </summary>
		protected virtual void OnListCompleted()
		{
			WaitOperation = false;
		}

		/// <summary>
		/// Manejador de Eventos para SaveCompletedEvent
		/// </summary>
		protected virtual void OnSaveCompleted()
		{
			WaitOperation = false;
			Clean();
			if (string.IsNullOrEmpty(ErrorMessage))
				ErrorMessage = "Registro grabado con éxito!";
		}

		#endregion

	}
}